package com.ruoyi.yl.utils;

import com.ruoyi.common.redis.service.RedisService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 分布式订单号生成器（基于Redis原子操作）
 */
@Component
public class OrderNoGenerator {

    @Resource
    private  RedisService redisService;
    
    // Redis key前缀
    private static final String ORDER_SEQ_KEY = "order_seq:";
    // 订单号前缀
    private static final String ORDER_PREFIX = "ORD";
    // 日期时间格式（精确到毫秒）
    private static final String DATE_TIME_FORMAT = "yyyyMMddHHmmssSSS";
    // 序列号长度
    private static final int SEQUENCE_LENGTH = 4;
    // 序列号最大值
    private static final int MAX_SEQUENCE = 9999;

  

    /**
     * 生成分布式唯一订单号
     * 格式：ORD + 17位时间戳 + 4位Redis序列号
     */
    public String generate() {
        // 1. 获取当前时间戳
        String timestamp = new SimpleDateFormat(DATE_TIME_FORMAT).format(new Date());
        
        // 2. 构造Redis key（按秒分组，避免单个key过大）
        String redisKey = ORDER_SEQ_KEY + timestamp.substring(0, 14); // 精确到秒
        
        // 3. 获取Redis自增序列（原子操作）
        Long sequence = redisService.increase(redisKey, 1);
        
        // 4. 如果是新创建的key，设置过期时间2秒（覆盖当前秒和下一秒）
        if (sequence == 1) {
            redisService.expire(redisKey, 2, TimeUnit.SECONDS);
        }
        
        // 5. 处理序列号溢出（理论上不会发生，因为1秒内很难达到MAX_SEQUENCE）
        if (sequence > MAX_SEQUENCE) {
            try {
                Thread.sleep(1); // 等待1毫秒
                return generate(); // 递归调用
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("生成订单号失败", e);
            }
        }
        
        // 6. 组合订单号
        return String.format("%s%s%0"+SEQUENCE_LENGTH+"d", ORDER_PREFIX, timestamp, sequence);
    }

    /**
     * 批量生成订单号（高效方式）
     * @param count 需要生成的数量
     */
    public String[] generateBatch(int count) {
        if (count <= 0 || count > 1000) {
            throw new IllegalArgumentException("生成数量必须在1-1000之间");
        }
        
        String timestamp = new SimpleDateFormat(DATE_TIME_FORMAT).format(new Date());
        String redisKey = ORDER_SEQ_KEY + timestamp.substring(0, 14);
        
        // 使用原子操作一次性获取一段序列号
        Long startSeq = redisService.increase(redisKey, count);
        
        // 设置过期时间
        if (startSeq <= count) {
            redisService.expire(redisKey, 2, TimeUnit.SECONDS);
        }
        
        String[] results = new String[count];
        for (int i = 0; i < count; i++) {
            long seq = startSeq - count + i + 1;
            if (seq > MAX_SEQUENCE) {
                // 如果溢出，则重新生成（理论上不会发生）
                return generateBatch(count);
            }
            results[i] = String.format("%s%s%0"+SEQUENCE_LENGTH+"d", 
                                      ORDER_PREFIX, timestamp, seq);
        }
        return results;
    }
}